package com.ruoyi.process.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.bussiness.service.ContantService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.process.constant.MultiInstanceConstants;
import com.ruoyi.process.domain.ApprObj;
import com.ruoyi.process.domain.Attachment;
import com.ruoyi.process.domain.workflow.ApprObjDTO;
import com.ruoyi.process.domain.workflow.ApprParam;
import com.ruoyi.process.domain.workflow.ApprQuery;
import com.ruoyi.process.mapper.TaskApprMapper;
import com.ruoyi.process.service.FlowServiceFactory;
import com.ruoyi.process.service.IFlowTaskService;
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.camunda.bpm.engine.runtime.Execution;
import org.camunda.bpm.engine.task.DelegationState;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService {
    private static final Logger log = LoggerFactory.getLogger(FlowTaskServiceImpl.class);
    @Resource
    private TaskApprMapper taskApprMapper;

    @Override
    public void agree(ApprParam params) {
        String taskId = params.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 是否委派
        DelegationState delegationState = task.getDelegationState();
        if (ObjectUtil.isNotNull(delegationState) && delegationState.equals(DelegationState.PENDING)) {
            // 2. 完成委托的任务
            taskService.resolveTask(taskId);
        } else {
            Map<String, Object> variables = new HashMap<>();
            variables = taskService.getVariables(taskId);
            variables.putAll(params.getApprSet());
            System.out.println("variables"+variables.toString());
            log.debug("variable",variables.toString());
            // 审批意见
            this.addComment(taskId, task.getProcessInstanceId(), params.getComment(), params.getAttachment());
            // 3. 完成任务
            taskService.complete(taskId, variables);
            // 4. 新增流转记录
            this.updateBusiness(params.getBusinessData());
        }
        //操作历史记录
    }

    private void updateBusiness(String bussinessData) {


    }

    //审批意见，带附件
    private void addComment(String taskId, String processInstanceId, String comment, List<Attachment> attachmentList) {
        //保存意见
        if (comment != null) {
            taskService.createComment(taskId, processInstanceId, comment);
            //增加附近功能
            if (attachmentList != null && attachmentList.size() > 0) {
                for (Attachment strattachobj : attachmentList) {
                    String suffix = "";
                    if (strattachobj.getName().contains(".") && !strattachobj.getName().endsWith(".")) {
                        suffix = strattachobj.getName().substring(strattachobj.getName().lastIndexOf(".") + 1);
                    } else {
                        if (strattachobj.getName().contains(".") && !strattachobj.getName().endsWith(".")) {
                            suffix = strattachobj.getName().substring(strattachobj.getName().lastIndexOf(".") + 1);
                        }
                    }
                    taskService.createAttachment(suffix, taskId, processInstanceId, strattachobj.getName(), null, strattachobj.getName());
                }
            }
        }
    }

    @Override
    public void refuse(ApprParam params) {
        String taskId = params.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();


        // 2. 获取任务模型
        BpmnModelInstance bpmnModel = repositoryService.getBpmnModelInstance(task.getProcessDefinitionId());
        UserTask userTask = bpmnModel.getModelElementById(task.getTaskDefinitionKey());
        Collection<SequenceFlow> outgoing = userTask.getOutgoing(); // 流出

        // 3. 判断是否是多实例
        LoopCharacteristics loopCharacteristics = userTask.getLoopCharacteristics();
        if (ObjectUtil.isNotNull(loopCharacteristics)) {
            // 3.1 多实例

            // 获取完成表达式
            CompletionCondition completionCondition = (CompletionCondition) loopCharacteristics.getUniqueChildElementByType(CompletionCondition.class);
            String conditionTextContent = completionCondition.getTextContent();

            // 直接用表达式判断是那种类型（实际开发，可以存入到 UserTask）
            if (MultiInstanceConstants.COMPLETE_CONDITION_HUI_QIAN_ALL_PASSED.equals(conditionTextContent)) {
                // 会签（需全部通过）
                // 直接完成并结束流程
                taskService.createComment(taskId, task.getProcessInstanceId(), params.getComment());// (String taskId, String processInstance, String message
                taskService.complete(taskId);
                endProcessIns(bpmnModel, task);
            } else if (MultiInstanceConstants.COMPLETE_CONDITION_HUI_QIAN_HALF.equals(conditionTextContent)) {
                // TODO 暂时未做
                Integer nrOfInstances = (Integer) taskService.getVariable(task.getId(), MultiInstanceConstants.NUMBER_OF_INSTANCES); // 实例总数
                Integer nrOfActiveInstances = (Integer) taskService.getVariable(task.getId(), MultiInstanceConstants.NUMBER_OF_ACTIVE_INSTANCES);// 当前未完成的实例数量
                taskService.getVariableLocalTyped(taskId, "nrOfInstances");
                Map<String, Object> variablesLocal = taskService.getVariablesLocal(MultiInstanceConstants.NUMBER_OF_INSTANCES);
                // 会签（半数通过）
            } else if (MultiInstanceConstants.COMPLETE_CONDITION_HUO_QIAN.equals(conditionTextContent)) {
                // 或签（一个通过即可）
                Integer nrOfActiveInstances = (Integer) taskService.getVariable(task.getId(), MultiInstanceConstants.NUMBER_OF_ACTIVE_INSTANCES);// 当前未完成的实例数量
                taskService.createComment(taskId, task.getProcessInstanceId(), params.getComment());// (String taskId, String processInstance, String message
                taskService.complete(taskId);// (String taskId, String processInstance, String message
                if (nrOfActiveInstances <= 1) { // 最后一票 结束流程
                    endProcessIns(bpmnModel, task);
                }
            } else {
                throw new RuntimeException("表达式有误");
            }
            //condition.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,"completionCondition");
            Map<String, Object> variables = runtimeService.getVariables(task.getProcessInstanceId());
        } else {
            // 3.2 单实例

            // 完成任务
            taskService.createComment(taskId, task.getProcessInstanceId(), params.getComment());// (String taskId, String processInstance, String message
            taskService.complete(taskId);
            // 结束流程（流转到结束节点）
            endProcessIns(bpmnModel, task);
        }

    }

    @Override
    public void transfer(ApprParam params) {
        // 1. 校验任务是否存在
        String taskId = params.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            throw new RuntimeException("未查询到任务");
        }

        // 2. 重新设置任务处理人
        String transferUserId = params.getTransferUserId();
        if (StrUtil.isEmpty(transferUserId)) {
            throw new RuntimeException("转办人不能为空");
        }
        taskService.setAssignee(task.getId(), transferUserId);
    }

    @Override
    public void delegate(ApprParam params) {
        // 1. 校验任务是否存在
        String taskId = params.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            throw new RuntimeException("未查询到任务");
        }

        // 2. 委派
        String delegateUserId = params.getDelegateUserId();
        if (StrUtil.isEmpty(delegateUserId)) {
            throw new RuntimeException("转办人不能为空");
        }
        taskService.delegateTask(task.getId(), delegateUserId);// 委派
    }

    @Override
    public void addsigntask(ApprParam params) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(params.getTaskId()).singleResult();
        if (taskEntity != null) {
            //如果是加签再加签
            //    String parentTaskId = taskEntity.getParentTaskId();
            //    if (StringUtils.isBlank(parentTaskId)) {
            taskEntity.setOwner(params.getUserId());
            taskEntity.setAssignee(null);
            //   taskEntity.setCountEnabled(true);
            if (params.getLabeltype() == 1) {
                taskEntity.setDescription("after");
            } else {
                taskEntity.setDescription("before");
            }
            taskEntity.setDelegationState(DelegationState.PENDING);
            //1.2 设置任务为空执行者
            taskService.saveTask(taskEntity);
            //  }
            //2.添加加签数据
            this.createSignSubTasks(params.getUserId(), taskEntity);
            //3.添加审批意见
            //附件
        }

    }

    @Override
    public List<ApprObj> getTodoList(ApprQuery params) {
        return taskApprMapper.selectToDoList();
    }

    @Override
    public List<ApprObjDTO> apprList(ApprQuery params) {
        return null;
    }

    @Override
    public List<ApprObjDTO> myprocessList(ApprQuery params) {
        return null;
    }

    /**
     * 创建加签子任务
     *
     * @param userid
     * @param taskEntity 父任务
     */
    private void createSignSubTasks(String userid, TaskEntity taskEntity) {
        String parentTaskId = taskEntity.getParentTaskId();
        if (StringUtils.isBlank(parentTaskId)) {
            parentTaskId = taskEntity.getId();
        }
        String finalParentTaskId = parentTaskId;
        //1.创建被加签人的任务列表
        this.createSubTask(taskEntity, userid);

    }

    protected TaskEntity createSubTask(TaskEntity ptask, String assignee) {
        TaskEntity task = null;
        if (ptask != null) {
            //他建execution
            //1.生成子任务
//            UuidGenerator uuidGenerator = new UuidGenerator();
            String strid = "stes3224234";
            task = (TaskEntity) taskService.newTask(strid);
            task.setDescription(ptask.getDescription());
            task.setTenantId(ptask.getTenantId());
            task.setAssignee(assignee);
            task.setName("审批");
//            task.setExecutionId(this.insertExecution(ptask));
            //   task.setParentTaskId(ptaskId);
            task.setParentTaskId(ptask.getId());
            task.setProcessDefinitionId(ptask.getProcessDefinitionId());
            task.setProcessInstanceId(ptask.getProcessInstanceId());

            Long overtime = 1596211200000l;
            Long nowtime = System.currentTimeMillis();
            String qutient = String.valueOf(nowtime - overtime);
            Random r = new Random();
            qutient = qutient + r.nextInt(1000);
            Long intqutient = Long.parseLong(qutient);
            String charts = "ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz";
            String arrchart[] = charts.split("");
            int radix = charts.length();
            String id = "";
            while (intqutient > 0) {
                Long strquti = intqutient % 52;
                Integer intquti = Integer.parseInt(String.valueOf(strquti));
                id = id + arrchart[intquti];
                intqutient = (intqutient - strquti) / radix;
            }
            task.setTaskDefinitionKey(id);

            //  task.setTaskDefinitionId(ptask.getTaskDefinitionId());
            task.setPriority(ptask.getPriority());
            task.setCreateTime(new Date());
            taskService.saveTask(task);
            taskService.setVariables(strid, taskService.getVariables(ptask.getId()));
        }
        return task;
    }

    private void endProcessIns(BpmnModelInstance bpmnModel, Task task) {
        Collection<EndEvent> endEvents = bpmnModel.getModelElementsByType(EndEvent.class);
        EndEvent endEvent = endEvents.stream().findFirst().get(); // 第一个结束节点
        List<Execution> executionList = runtimeService.createExecutionQuery() // 所有正在执行的节点
                .processInstanceId(task.getProcessInstanceId())
                .active()
                .list();
        if (CollUtil.isNotEmpty(executionList)) { // 所有正在执行的节点直接调转到结束节点
            for (Execution execution : executionList) {
                runtimeService.createModification(task.getProcessDefinitionId())
                        .processInstanceIds(task.getProcessInstanceId())
                        .cancelAllForActivity(execution.getId())
                        .startBeforeActivity(endEvent.getId())
                        .execute();
            }
        }
    }
}
